summaryrefslogtreecommitdiff
path: root/app/[lng]/partners/(partners)
diff options
context:
space:
mode:
Diffstat (limited to 'app/[lng]/partners/(partners)')
-rw-r--r--app/[lng]/partners/(partners)/basic-contract/page.tsx77
-rw-r--r--app/[lng]/partners/(partners)/cbe/page.tsx86
-rw-r--r--app/[lng]/partners/(partners)/dashboard/page.tsx53
-rw-r--r--app/[lng]/partners/(partners)/document-list/layout.tsx8
-rw-r--r--app/[lng]/partners/(partners)/documents/layout.tsx8
-rw-r--r--app/[lng]/partners/(partners)/report/page.tsx17
-rw-r--r--app/[lng]/partners/(partners)/vendor-data/form/[packageId]/[formId]/page.tsx41
-rw-r--r--app/[lng]/partners/(partners)/vendor-data/layout.tsx8
-rw-r--r--app/[lng]/partners/(partners)/vendor-data/page.tsx2
9 files changed, 268 insertions, 32 deletions
diff --git a/app/[lng]/partners/(partners)/basic-contract/page.tsx b/app/[lng]/partners/(partners)/basic-contract/page.tsx
new file mode 100644
index 00000000..e63e6a17
--- /dev/null
+++ b/app/[lng]/partners/(partners)/basic-contract/page.tsx
@@ -0,0 +1,77 @@
+import * as React from "react"
+import { type SearchParams } from "@/types/table"
+import { getValidFilters } from "@/lib/data-table"
+import { Skeleton } from "@/components/ui/skeleton"
+import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
+import { Shell } from "@/components/shell"
+import { getBasicContractsByVendorId } from "@/lib/basic-contract/service"
+import { searchParamsCache } from "@/lib/basic-contract/validations"
+import { redirect } from "next/navigation"
+import { BasicContractsVendorTable } from "@/lib/basic-contract/vendor-table/basic-contract-table"
+import { getServerSession } from "next-auth"
+import { authOptions } from "@/app/api/auth/[...nextauth]/route"
+
+interface IndexPageProps {
+ searchParams: Promise<SearchParams>
+}
+
+export default async function IndexPage(props: IndexPageProps) {
+
+
+ const session = await getServerSession(authOptions)
+ const vendorId = session?.user.companyId
+
+ const searchParams = await props.searchParams
+ const search = searchParamsCache.parse(searchParams)
+
+ const validFilters = getValidFilters(search.filters)
+
+ const promises = Promise.all([
+ getBasicContractsByVendorId(
+ {
+ ...search,
+ filters: validFilters,
+ },
+ Number(vendorId)
+ ),
+ ])
+
+ return (
+ <Shell className="gap-2">
+ <div className="flex items-center justify-between space-y-2">
+ <div className="flex items-center justify-between space-y-2">
+ <div>
+ <h2 className="text-2xl font-bold tracking-tight">
+ 기본계약서 서명 요청현황
+ </h2>
+ <p className="text-muted-foreground">
+ 기본계약서를 비롯하여 초기 서명이 필요한 문서의 서명 현황을 확인할 수 있고 서명을 진행할 수 있습니다. {" "}
+ </p>
+ </div>
+ </div>
+ </div>
+
+ <React.Suspense fallback={<Skeleton className="h-7 w-52" />}>
+ {/* <DateRangePicker
+ triggerSize="sm"
+ triggerClassName="ml-auto w-56 sm:w-60"
+ align="end"
+ shallow={false}
+ /> */}
+ </React.Suspense>
+ <React.Suspense
+ fallback={
+ <DataTableSkeleton
+ columnCount={6}
+ searchableColumnCount={1}
+ filterableColumnCount={2}
+ cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]}
+ shrinkZero
+ />
+ }
+ >
+ <BasicContractsVendorTable promises={promises} />
+ </React.Suspense>
+ </Shell>
+ )
+} \ No newline at end of file
diff --git a/app/[lng]/partners/(partners)/cbe/page.tsx b/app/[lng]/partners/(partners)/cbe/page.tsx
new file mode 100644
index 00000000..8d03e5f6
--- /dev/null
+++ b/app/[lng]/partners/(partners)/cbe/page.tsx
@@ -0,0 +1,86 @@
+import { type SearchParams } from "@/types/table"
+import { getValidFilters } from "@/lib/data-table"
+import { getCBEbyVendorId, } from "@/lib/rfqs/service"
+import { searchParamsCBECache } from "@/lib/rfqs/validations"
+import { getServerSession } from "next-auth"
+import { authOptions } from "@/app/api/auth/[...nextauth]/route"
+import { TbeVendorTable } from "@/lib/vendor-rfq-response/vendor-tbe-table/tbe-table"
+import * as React from "react"
+import { Skeleton } from "@/components/ui/skeleton"
+import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
+import { Shell } from "@/components/shell"
+import { CbeVendorTable } from "@/lib/vendor-rfq-response/vendor-cbe-table/cbe-table"
+
+interface IndexPageProps {
+ // Next.js 13 App Router에서 기본으로 주어지는 객체들
+ params: {
+ lng: string
+ id: string
+ }
+ searchParams: Promise<SearchParams>
+}
+
+export default async function CBEPage(props: IndexPageProps) {
+ const resolvedParams = await props.params
+ const lng = resolvedParams.lng
+
+ // 2) SearchParams 파싱 (Zod)
+ // - "filters", "page", "perPage", "sort" 등 contact 전용 컬럼
+ const searchParams = await props.searchParams
+ const search = searchParamsCBECache.parse(searchParams)
+ const validFilters = getValidFilters(search.filters)
+
+ const session = await getServerSession(authOptions)
+ const vendorId = session?.user.companyId
+ // const vendorId = "17"
+
+ const idAsNumber = Number(vendorId)
+
+ const promises = Promise.all([
+ getCBEbyVendorId({
+ ...search,
+ filters: validFilters,
+ },
+ idAsNumber)
+ ])
+
+
+ return (
+ <Shell className="gap-2">
+ <div className="flex items-center justify-between space-y-2">
+ <div className="flex items-center justify-between space-y-2">
+ <div>
+ <h2 className="text-2xl font-bold tracking-tight">
+ Commercial Bid Evaluation
+ </h2>
+ <p className="text-sm text-muted-foreground">
+ CBE에 응답하고 커뮤니케이션을 할 수 있습니다.{" "}
+ </p>
+ </div>
+ </div>
+ </div>
+
+ <React.Suspense fallback={<Skeleton className="h-7 w-52" />}>
+ {/* <DateRangePicker
+ triggerSize="sm"
+ triggerClassName="ml-auto w-56 sm:w-60"
+ align="end"
+ shallow={false}
+ /> */}
+ </React.Suspense>
+ <React.Suspense
+ fallback={
+ <DataTableSkeleton
+ columnCount={6}
+ searchableColumnCount={1}
+ filterableColumnCount={2}
+ cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]}
+ shrinkZero
+ />
+ }
+ >
+ <CbeVendorTable promises={promises} />
+ </React.Suspense>
+ </Shell>
+ )
+}
diff --git a/app/[lng]/partners/(partners)/dashboard/page.tsx b/app/[lng]/partners/(partners)/dashboard/page.tsx
index a1e9f8be..3efaa7c3 100644
--- a/app/[lng]/partners/(partners)/dashboard/page.tsx
+++ b/app/[lng]/partners/(partners)/dashboard/page.tsx
@@ -1,8 +1,47 @@
+import * as React from "react"
+import { Skeleton } from "@/components/ui/skeleton"
+import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
+import { Shell } from "@/components/shell"
-export default function Pages() {
- return (
- <>
- test
- </>
- )
- } \ No newline at end of file
+
+
+export default async function IndexPage() {
+
+
+ return (
+ <Shell className="gap-2">
+ <div className="flex items-center justify-between">
+ <div>
+ <h2 className="text-2xl font-bold tracking-tight">
+ Dashboard
+ </h2>
+ <p className="text-muted-foreground">
+ 각종 지표 등을 대시보드로 표현하거나 리포트를 출력할 수 있습니다.
+ </p>
+ </div>
+ </div>
+
+ <React.Suspense fallback={<Skeleton className="h-7 w-52" />}>
+ {/* <DateRangePicker
+ triggerSize="sm"
+ triggerClassName="ml-auto w-56 sm:w-60"
+ align="end"
+ shallow={false}
+ /> */}
+ </React.Suspense>
+
+ <React.Suspense
+ fallback={
+ <DataTableSkeleton
+ columnCount={6}
+ searchableColumnCount={1}
+ filterableColumnCount={2}
+ cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]}
+ shrinkZero
+ />
+ }
+ >
+ </React.Suspense>
+ </Shell>
+ )
+} \ No newline at end of file
diff --git a/app/[lng]/partners/(partners)/document-list/layout.tsx b/app/[lng]/partners/(partners)/document-list/layout.tsx
index a75cdf7d..0eb9d27b 100644
--- a/app/[lng]/partners/(partners)/document-list/layout.tsx
+++ b/app/[lng]/partners/(partners)/document-list/layout.tsx
@@ -6,6 +6,8 @@ import { getVendorProjectsAndContracts } from "@/lib/vendor-data/services"
import { getVendorDocumentLists } from "@/lib/vendor-document/service"
import VendorDocumentsClient from "@/components/documents/vendor-docs.client"
import VendorDocumentListClient from "@/components/document-lists/vendor-doc-list-client"
+import { authOptions } from "@/app/api/auth/[...nextauth]/route";
+import { getServerSession } from "next-auth";
@@ -15,9 +17,9 @@ export default async function VendorDocuments({
}: {
children: React.ReactNode
}) {
- // const session = await getServerSession(authOptions)
- // const vendorId = session?.user.companyId
- const vendorId = "17"
+ const session = await getServerSession(authOptions)
+ const vendorId = session?.user.companyId
+ // const vendorId = "17"
const idAsNumber = Number(vendorId)
const projects = await getVendorProjectsAndContracts(idAsNumber)
diff --git a/app/[lng]/partners/(partners)/documents/layout.tsx b/app/[lng]/partners/(partners)/documents/layout.tsx
index 3ac0c573..dcc2c271 100644
--- a/app/[lng]/partners/(partners)/documents/layout.tsx
+++ b/app/[lng]/partners/(partners)/documents/layout.tsx
@@ -5,6 +5,8 @@ import DocumentContainer from "@/components/documents/document-container"
import { getVendorProjectsAndContracts } from "@/lib/vendor-data/services"
import { getVendorDocumentLists } from "@/lib/vendor-document/service"
import VendorDocumentsClient from "@/components/documents/vendor-docs.client"
+import { authOptions } from "@/app/api/auth/[...nextauth]/route";
+import { getServerSession } from "next-auth";
@@ -14,9 +16,9 @@ export default async function VendorDocuments({
}: {
children: React.ReactNode
}) {
- // const session = await getServerSession(authOptions)
- // const vendorId = session?.user.companyId
- const vendorId = "17"
+ const session = await getServerSession(authOptions)
+ const vendorId = session?.user.companyId
+ // const vendorId = "17"
const idAsNumber = Number(vendorId)
const projects = await getVendorProjectsAndContracts(idAsNumber)
diff --git a/app/[lng]/partners/(partners)/report/page.tsx b/app/[lng]/partners/(partners)/report/page.tsx
new file mode 100644
index 00000000..1d61dc16
--- /dev/null
+++ b/app/[lng]/partners/(partners)/report/page.tsx
@@ -0,0 +1,17 @@
+// app/invalid-access/page.tsx
+
+export default function InvalidAccessPage() {
+ return (
+ <main style={{ padding: '40px', textAlign: 'center' }}>
+ <h1>부적절한 접근입니다</h1>
+ <p>
+ 협력업체(Vendor)가 EVCP 화면에 접속하거나 <br />
+ SHI 계정이 협력업체 화면에 접속하려고 시도하는 경우입니다.
+ </p>
+ <p>
+ <strong>접근 권한이 없으므로, 다른 화면으로 이동해 주세요.</strong>
+ </p>
+ </main>
+ );
+ }
+ \ No newline at end of file
diff --git a/app/[lng]/partners/(partners)/vendor-data/form/[packageId]/[formId]/page.tsx b/app/[lng]/partners/(partners)/vendor-data/form/[packageId]/[formId]/page.tsx
index 01f5b501..dc8df262 100644
--- a/app/[lng]/partners/(partners)/vendor-data/form/[packageId]/[formId]/page.tsx
+++ b/app/[lng]/partners/(partners)/vendor-data/form/[packageId]/[formId]/page.tsx
@@ -7,32 +7,41 @@ interface IndexPageProps {
packageId: string;
formId: string;
};
+ searchParams?: {
+ mode?: string;
+ };
}
-export default async function FormPage({ params }: IndexPageProps) {
+export default async function FormPage({ params, searchParams }: IndexPageProps) {
// 1) 구조 분해 할당
const resolvedParams = await params;
-
- // 2) 구조 분해 할당
+
+ // 2) searchParams도 await 필요
+ const resolvedSearchParams = await searchParams;
+
+ // 3) 구조 분해 할당
const { lng, packageId, formId: formCode } = resolvedParams;
-
- // 2) 변환
+
+ // URL 쿼리 파라미터에서 mode 가져오기 (await 해서 사용)
+ const mode = resolvedSearchParams?.mode === "ENG" ? "ENG" : "IM"; // 기본값은 IM
+
+ // 4) 변환
const packageIdAsNumber = Number(packageId);
-
- // 3) DB 조회
- const { columns, data } = await getFormData(formCode, packageIdAsNumber);
-
- // 4) formId 및 report temp file 조회
+
+ // 5) DB 조회
+ const { columns, data, projectId } = await getFormData(formCode, packageIdAsNumber);
+
+ // 6) formId 및 report temp file 조회
const { formId } = await getFormId(packageId, formCode);
-
- // 5) 예외 처리
+
+ // 7) 예외 처리
if (!columns) {
return (
<p className="text-red-500">해당 폼의 메타 정보를 불러올 수 없습니다.</p>
);
}
-
- // 5) 렌더링
+
+ // 8) 렌더링
return (
<div className="space-y-6">
<DynamicTable
@@ -41,7 +50,9 @@ export default async function FormPage({ params }: IndexPageProps) {
formId={formId}
columnsJSON={columns}
dataJSON={data}
+ projectId={projectId}
+ mode={mode} // 모드 전달
/>
</div>
);
-}
+} \ No newline at end of file
diff --git a/app/[lng]/partners/(partners)/vendor-data/layout.tsx b/app/[lng]/partners/(partners)/vendor-data/layout.tsx
index a8b51c52..29a720de 100644
--- a/app/[lng]/partners/(partners)/vendor-data/layout.tsx
+++ b/app/[lng]/partners/(partners)/vendor-data/layout.tsx
@@ -4,6 +4,8 @@ import { cookies } from "next/headers"
import { Shell } from "@/components/shell"
import { getVendorProjectsAndContracts } from "@/lib/vendor-data/services"
import { VendorDataContainer } from "@/components/vendor-data/vendor-data-container"
+import { authOptions } from "@/app/api/auth/[...nextauth]/route";
+import { getServerSession } from "next-auth";
// Layout 컴포넌트는 서버 컴포넌트입니다
export default async function VendorDataLayout({
@@ -11,9 +13,9 @@ export default async function VendorDataLayout({
}: {
children: React.ReactNode
}) {
- // const session = await getServerSession(authOptions)
- // const vendorId = session?.user.companyId
- const vendorId = "17"
+ const session = await getServerSession(authOptions)
+ const vendorId = session?.user.companyId
+ // const vendorId = "17"
const idAsNumber = Number(vendorId)
// 프로젝트 데이터 가져오기
diff --git a/app/[lng]/partners/(partners)/vendor-data/page.tsx b/app/[lng]/partners/(partners)/vendor-data/page.tsx
index 3eead226..afc3932c 100644
--- a/app/[lng]/partners/(partners)/vendor-data/page.tsx
+++ b/app/[lng]/partners/(partners)/vendor-data/page.tsx
@@ -6,7 +6,7 @@ export default async function IndexPage() {
return (
<div className="space-y-6">
<div>
- <h3 className="text-lg font-medium">벤더 데이터 대시보드</h3>
+ <h3 className="text-lg font-medium">협력업체 데이터 대시보드</h3>
<p className="text-sm text-muted-foreground">
왼쪽 사이드바에서 패키지를 선택하여 태그를 관리하세요.
</p>